-- element_damage
-- create by panyl
-- 元素球

return {
    apply = function(source, target, skillId, round, para, extra)
        -- 威力
        local force = para[1];

        -- 计算魔法效果加成
        local addon_rate = SkillM.calcMagicEffectAddon(source, skillId, true);
        local prop;

        local combine = PropM.combine;
        local PropM_apply = PropM.apply;
        local fetchProps = PropM.fetchProps;
        local trigger = PropM.trigger;

        -- 对某系有额外加成
        if #para > 1 then
            local rate = para[3];
            if type(para[2]) == 'table' then
                -- 配置了多个系别
                for _, style in pairs(para[2]) do
                    if tonumber(style) == target.style then
                        prop = combine(source, "holy_light", tonumber(style));
                        rate = PropM_apply(prop, rate);
                        addon_rate = addon_rate + rate;
                        break;
                    end
                end
            elseif para[2] == target.style then
                -- 单个系别
                prop = combine(source, "holy_light", para[2]);
                rate = PropM_apply(prop, rate);
                addon_rate = addon_rate + rate;
            end
        end

        --最终威力
        local force = math.modf(force * (addon_rate + 1000)/1000);

        -- 2. 攻击方的魔力
        local magic = source:getMagic();

        -- 被对方百分比削弱
        prop = combine(target, "weak_enemy", "magic");
        magic = PropM_apply(prop, magic);

        -- 被对方绝对值削弱
        prop = combine(target, "weak_enemy2", "magic");
        magic = PropM_apply(prop, magic);

        -- 3. 伤害/计算伤害时魔力+3
        local damage = math.modf(force * (magic + 3) / 1000);

        -- 魔法暴击类，多种暴击线性叠加伤害
        local addon_damage = 0;

        -- 伤害类魔法概率增强
        local props = fetchProps(source, "damage_magic");
        for _, prop in ipairs(props) do
            addon_damage = addon_damage + trigger(source, prop[1], prop[2], damage);
        end
        -- 魔法暴击
        props = fetchProps(source, "critical_magic");
        for _, prop in ipairs(props) do
            addon_damage = addon_damage + trigger(source, prop[1], prop[2], damage);
        end
        -- 概率双倍
        props = fetchProps(source, "skill_double");
        for _, prop in ipairs(props) do
            if tonumber(prop[2]) == skillId then
                addon_damage = addon_damage + trigger(source, prop[1], prop[2], damage);
            end
        end

        -- 最终伤害
        damage = damage + addon_damage;

        -- 4. 魔法抗性
        prop = combine(target, "resist", "magic");
        -- 忽视抗性
        local p = combine(source, "ignore_resist", skillId);
        prop[3] = PropM_apply(p, prop[3]);
        p = combine(source, "ignore_resist", "magic");
        prop[3] = PropM_apply(p, prop[3]);

        -- 元素球无视魔法抗性
        p = combine(source, "ignore_resist", "element_magic");
        prop[3] = PropM_apply(p, prop[3]);

        -- 天赋概率无视抗性
        local p = combine(source, "disre_resist", skillId);
        local seed = DungeonM.getRandSeed("disre_resist");
        if seed % 1000 < PropM_apply(p, 1) then
            prop[3] = 0;
        end

        damage = PropM_apply(prop, damage);

        -- 元素球对某类怪物伤害加成
        prop = combine(source, "element_aim", target.style);
        damage = PropM_apply(prop, damage);

        -- 元素球伤害+
        prop = combine(source, "element_aim", "*");
        damage = PropM_apply(prop, damage);

        -- 目标害怕某技能，直接被击杀
        prop = combine(target, "afraid_skill", skillId);
        if PropM_apply(prop, 1) > 0 then
            damage = math.max(damage, target:getHp());
        end

        -- 增加命中动作
        SkillM.getSequence(target):hit(source, target, skillId);

        -- 伤害
        CombatM.receiveDamage(source, target, damage, skillId, extra);

        -- 溅射周围
        prop = combine(source, "element_spurt", 1);
        if prop[3] > 0 then
            for _, pos in pairs(DungeonM.getAroundGrids(target:getPos())) do
                repeat
                    local grid = DungeonM.getGridByPos(pos);
                    local monster = grid.monster;

                    -- 如果还未翻开
                    if not grid:isOpened() then
                        grid:open();
                    end

                    if not monster or monster:isDead() then
                        break;
                    end

                    SkillM.initSequence(source, monster, skillId);

                    -- 受创
                    SkillM.getSequence(monster):hit(source, monster, skillId);

                    -- 伤害
                    CombatM.receiveDamage(source, monster, math.floor(damage / 2), skillId, extra);
                until true;
            end
        end

        -- 没免疫
        if not SkillM.immunitySkill(source, target, skillId) then
            -- 冰冻
            prop = combine(source, "element_freeze", 1);
            trigger(source, prop[1], prop[2], target);

            -- 额外附带燃烧效果，在造成伤害后
            prop = combine(source, "skill_add_burn", skillId);
            trigger(source, prop[1], prop[2], target);

            -- 元素燃烧
            prop = combine(source, "element_burn", 1);
            trigger(source, prop[1], prop[2], target);
        end

        -- 施放技能增加装备经验
        prop = combine(source, "skill_add_exp", skillId);
        if prop[3] > 0 then
            trigger(source, prop[1], prop[2]);
        end

        -- 如果是玩家，抛出攻击结果事件
        if source.type == OBJECT_TYPE_USER then
            EventMgr.fire(event.HERO_ATTACK_RESULT, { ["damage"] = damage, ["extra"] = extra});
        end

        -- 作用目标
        return { target, };
    end,

    parse = function(desc)
        local arr = string.explode(desc, ",");
        if (#arr == 1) then
            return { tonumber(arr[1]), };
        else
            local styleList = string.explode(arr[2], "+");
            if #styleList > 1 then
                return { tonumber(arr[1]), styleList, tonumber(arr[3]) };
            else
                return { tonumber(arr[1]), tonumber(arr[2]), tonumber(arr[3]) };
            end
        end
    end,

    -- 解析技能描述
    parseDesc = function(source, skillId, desc, para)
        -- 威力
        local base = para[1];

        local addon_rate = 0;
        -- 威力加成,先计算总的提升率，再计算威力
        local prop = PropM.combine(source, "magic_effect", skillId);
        addon_rate = addon_rate + PropM.apply(prop, 1);
        -- 某系技能威力加成
        prop = PropM.combine(source, "magic_effect_style", SkillM.query(skillId, "style"));
        addon_rate = addon_rate + PropM.apply(prop, 1);

        -- 某系技能威力加成（光与暗）
        prop = PropM.combine(source, "light_and_dark", SkillM.query(skillId, "style"));
        addon_rate = addon_rate + PropM.apply(prop, 1);

        -- 某系技能威力加成（水元素操控）
        prop = PropM.combine(source, "water_control", SkillM.query(skillId, "style"));
        addon_rate = addon_rate + PropM.apply(prop, 1);

        -- 某系技能威力加成（离子风暴）
        prop = PropM.combine(source, "lon_storm", SkillM.query(skillId, "style"));
        addon_rate = addon_rate + PropM.apply(prop, 1);

        -- 某系技能威力加成（海神）
        prop = PropM.combine(source, "poseidon", SkillM.query(skillId, "style"));
        addon_rate = addon_rate + PropM.apply(prop, 1);

        -- 某系技能威力加成（火元素操控）
        prop = PropM.combine(source, "fire_control", SkillM.query(skillId, "style"));
        addon_rate = addon_rate + PropM.apply(prop, 1);

        -- 所有系技能威力加成
        prop = PropM.combine(source, "magic_effect_style", "all");
        addon_rate = addon_rate + PropM.apply(prop, 1);

        -- 所有系技能威力加成（永恒）
        prop = PropM.combine(source, "eternal", "all");
        addon_rate = addon_rate + PropM.apply(prop, 1);

        -- 伤害魔法威力加成
        prop = PropM.combine(source, "magic_effect_style", "damage");
        addon_rate = addon_rate + PropM.apply(prop, 1);
        -- 低阶伤害魔法威力加成
        if SkillM.query(skillId,"rank") < 3 then
            prop = PropM.combine(source, "powerful_spell", 1);
            addon_rate = addon_rate + PropM.apply(prop, 1);
        end

        -- 高阶伤害魔法威力加成
        if SkillM.query(skillId,"rank") > 3 then
            prop = PropM.combine(source, "powerful_spell2", 1);
            addon_rate = addon_rate + PropM.apply(prop, 1);
        end

        --最终威力
        local force = math.modf(base * (addon_rate + 1000)/1000);

        -- 2. 攻击方的魔力
        local magic = source:getMagic();

        -- 3. 伤害
        local damageBase = math.modf(base * (magic + 3) / 1000);
        local damageForce = math.modf(force * (magic + 3) / 1000);
        local damageAddon = damageForce - damageBase;
        if damageAddon == 0 then
            desc = string.gsub(desc, "{damage}", damageForce);
        else
            desc = string.gsub(desc, "{damage}", damageBase .. "(+" .. damageAddon .. ")");
        end

        local key = FormulaM.invoke("CALC_SKILL_APPEND_PROP", skillId);
        if key then
            prop = PropM.combine(source, key, skillId);
        end
        local append = math.modf(PropM.apply(prop, 1) / 10);
        desc = string.gsub(desc, "{append}", append);

        -- 连携特效
        local map = {
            [9]  = { 111, "earth_connect",  },
            [19] = { 112, "ice_connect",    },
            [29] = { 113, "fire_connect",   },
            [39] = { 114, "thunder_connect", },
            [49] = { 115, "lighter_connect", },
            [59] = { 116, "dark_connect",    },
        };

        local connect_desc = "";
        local _desc = "";

        for id, arr in pairs(map) do
            if id == skillId then
                desc = desc .. "\n" .. getLocStr(arr[2]) .. "\n";
            else
                local pet_info = PetM.query(arr[1]);
                local line = string.format(getLocStr("pet_connect_tip"), pet_info["name"]) ..  getLocStr(arr[2]) .. "\n";

                if PetM.isLictorPet(arr[1]) or PetM.isActivePet(arr[1]) then
                    connect_desc = connect_desc .. line;
                else
                    _desc = _desc .. line;
                end
            end
        end

        desc = string.format("%s\n[blue]%s[-][gray]%s[-]", desc, connect_desc, _desc);

        -- desc = desc .. "\n" .. "[blue]" .. connect_desc .. _desc;

        return desc;
    end,
};
